package com.yyfax.pay.common.util;

import java.lang.reflect.Field;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import javax.persistence.Transient;

import org.apache.commons.lang3.StringUtils;
import org.springframework.util.ReflectionUtils;

import com.alibaba.fastjson.annotation.JSONField;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.yyfax.pay.common.annotation.Alias;
import com.yyfax.pay.common.util.CheckSignUtils.FieldCallbacks;

/**
 * 别名工具类
 * 
 * @author buyi
 * @date 2017-08-31 08:55:46
 * @since v2.0.0
 */
public class AliasUtil {
	/** 符号-等号 */
	private static final String SYMBOL_EQUAL = "=";

	/**
	 * 拼装实体值
	 * 
	 * @author buyi
	 * @date 2017-09-01 11:05:42
	 * @since v2.0.0
	 * @param obj
	 * @param split
	 * @return
	 */
	public static String mergeObjectValues(Object obj, String split) {
		Map<String, String> map = coverToMap(obj);

		List<String> names = Lists.newArrayList(map.keySet());
		List<String> values = Lists.newArrayList();
		Collections.sort(names, String.CASE_INSENSITIVE_ORDER);
		for (String name : names) {
			values.add(map.get(name));
		}

		return StringUtils.join(values, split);
	}

	/**
	 * 合并实例对象域，并按照spilt规则拼装
	 * 
	 * @author buyi
	 * @date 2017-09-01 23:35:21
	 * @since v2.0.0
	 * @param obj
	 * @param split
	 * @return key1=value[split]key2=value[split]key3=value
	 */
	public static String mergeObjectFields(Object obj, String split) {
		List<String> list = coverToList(obj);

		return StringUtils.join(list, split);
	}

	/**
	 * 组装对象实例域，并用“=”拼装fieldName和value
	 *
	 * @author buyi
	 * @date 2017-09-01 23:35:21
	 * @since v2.0.0
	 * @param obj
	 * @return
	 */
	public static List<String> coverToList(Object obj) {
		List<String> list = Lists.newArrayList();

		Map<String, String> map = coverToMap(obj);
		for (String key : map.keySet()) {
			list.add(key.concat(SYMBOL_EQUAL).concat(map.get(key)));
		}

		Collections.sort(list, String.CASE_INSENSITIVE_ORDER);

		return list;
	}

	/**
	 * 实体对象实例域转换成map
	 *
	 * @author buyi
	 * @date 2017-09-01 23:35:21
	 * @since v2.0.0
	 * @param obj
	 * @return
	 */
	public static Map<String, String> coverToMap(Object obj) {
		final List<Field> fields = Lists.newArrayList();
		ReflectionUtils.doWithFields(obj.getClass(), new FieldCallbacks() {

			@Override
			public void doWith(Field field) {
				// 过滤Transient注解的字段
				Transient anno = field.getAnnotation(Transient.class);
				if (anno != null) {
					return;
				}
				field.setAccessible(true);
				fields.add(field);
			}

		});

		Map<String, String> map = Maps.newHashMap();

		for (Field field : fields) {
			String name = field.getName();
			Object object = ReflectionUtils.getField(field, obj);
			String value = object == null ? "" : String.valueOf(object);

			Alias alias = field.getAnnotation(Alias.class);
			JSONField jsonField = field.getAnnotation(JSONField.class);
			XStreamAlias xStreamAlias = field.getAnnotation(XStreamAlias.class);
			if (alias != null && StringUtils.isNotBlank(alias.value())) {
				name = alias.value();
			} else if (jsonField != null && StringUtils.isNotBlank(jsonField.name())) {
				name = jsonField.name();
			} else if (xStreamAlias != null && StringUtils.isNotBlank(xStreamAlias.value())) {
				name = xStreamAlias.value();
			}

			if (map.containsKey(name)) {
				throw new IllegalStateException("the alias is duplicate");
			}

			map.put(name, value);
		}

		return map;
	}

	/**
	 * 转换实体对象为map
	 * 
	 * @author buyi
	 * @date 2018-06-19 19:27:06
	 * @since v2.2.2
	 * @param obj
	 * @return
	 */
	public static Map<String, String> coverToMapAll(Object obj) {
		final List<Field> fields = Lists.newArrayList();
		ReflectionUtils.doWithFields(obj.getClass(), new FieldCallbacks() {

			@Override
			public void doWith(Field field) {
				field.setAccessible(true);
				fields.add(field);
			}

		});

		Map<String, String> map = Maps.newHashMap();

		for (Field field : fields) {
			String name = field.getName();
			Object object = ReflectionUtils.getField(field, obj);
			String value = object == null ? "" : String.valueOf(object);

			Alias alias = field.getAnnotation(Alias.class);
			JSONField jsonField = field.getAnnotation(JSONField.class);
			XStreamAlias xStreamAlias = field.getAnnotation(XStreamAlias.class);
			if (alias != null && StringUtils.isNotBlank(alias.value())) {
				name = alias.value();
			} else if (jsonField != null && StringUtils.isNotBlank(jsonField.name())) {
				name = jsonField.name();
			} else if (xStreamAlias != null && StringUtils.isNotBlank(xStreamAlias.value())) {
				name = xStreamAlias.value();
			}

			if (map.containsKey(name)) {
				throw new IllegalStateException("the alias is duplicate");
			}

			map.put(name, value);
		}

		return map;
	}

	// public static void main(String[] args) {
	// FuiouEbankFormVO form = new FuiouEbankFormVO();
	// String str = AliasUtil.mergeObjectFields(form, "|");
	// System.out.println(str);
	//
	// System.out.println(JSON.toJSONString(form, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullStringAsEmpty));
	// System.out.println(JacksonUtil.toJson(form));
	// }
}
